home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / files.swg / 0096_File disk storage and retrieval program.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-11-29  |  14.4 KB  |  512 lines

  1. program CAT;
  2.  
  3. {$I-}
  4.  
  5. uses
  6.    dos,
  7.    files, { see end for this unit }
  8.    crt;
  9.  
  10. type
  11.    arraybuf = array[1..65535] of byte;
  12.    buffer = ^arraybuf;
  13.    chksum = file of searchrec;
  14.  
  15. procedure error(mess:string);
  16. var
  17.    code:integer;
  18. begin
  19.    code:= ioresult;
  20.    writeln('ERROR:  ', mess);
  21.    {writeln('ERROR CODE:  ', code);}
  22.    halt(1);
  23. end;
  24.  
  25. procedure delete(drive:char; var success:boolean);
  26.    procedure recurse(tree:directory_tree; var success:boolean);
  27.    var
  28.       info:searchrec;
  29.       buffer:text;
  30.       success2:boolean;
  31.       d:string[79];
  32.    begin
  33.       if tree <> nil then begin
  34.       success2:= true;
  35.       d:= tree^.dir;
  36.          begin
  37.             recurse(tree^.lower_dir, success2);
  38.             tree:= tree^.next;
  39.             success:= success and success2;
  40.             recurse(tree, success2);
  41.             success:= success and success2;
  42.          end;
  43.       chdir(d);
  44.       findfirst('*.*', anyfile, info);
  45.       while (doserror = 0) and (success) do
  46.          begin
  47.             if (info.name <> '.') and (info.name <> '..') then
  48.                begin
  49.                   assign(buffer, info.name);
  50.                   case info.attr of
  51.                      $10: rmdir(info.name);
  52.                      $20: erase(buffer);
  53.                   else
  54.                      success:= false;
  55.                   end;
  56.                end;
  57.             findnext(info);
  58.          end;
  59.    end;
  60.    end;
  61. var
  62.    tree:directory_tree;
  63. begin
  64.    tree:= nil;
  65.    chdir(drive+':\');
  66.    fill_dirtree(drive+':\', tree);
  67.    success:= true;
  68.    recurse(tree, success);
  69. end;
  70.  
  71. function DriveExist(drive:char):boolean;
  72. var
  73.    fileinfo:searchrec;
  74. begin
  75.    findfirst(drive+':\*.*', anyfile, fileinfo);
  76.    if doserror = 3 then
  77.       driveexist:= false
  78.    else
  79.       driveexist:= true;
  80. end;
  81.  
  82. procedure work(max,done:longint);
  83. begin
  84.    write(100*(done/max):4:1, '% complete.');
  85.    gotoxy(1, wherey);
  86. end;
  87.  
  88. procedure help;
  89. begin
  90.    writeln('The Concatinator   Version 1.0   Copyright 1996 by Jack Neely');
  91.    writeln('A large file disk storage and retrieval program.');
  92.    writeln;
  93.    writeln('Usage:   CAT s <storage drive> <filename>');
  94.    writeln('         CAT r <storage dirve> <path>');
  95.    writeln;
  96.    writeln('Commands: ''s'' = Store   ''r'' = Retrive');
  97.    writeln('Storage drive must be the disk drive to store or that a large file is');
  98.    writeln('stored apon.  Specify a path where the file will be placed when');
  99.    writeln('retriving a file.  Specify a filemane when storing a large file.');
  100.    writeln;
  101.    writeln('You can use this program to store those large files that are larger');
  102.    writeln('than a single disk onto multiple disks.  Anything on the disk prior');
  103.    writeln('to storage will be erased.  A checksum file will also be stored on the');
  104.    writeln('first disk of each set.');
  105.    writeln;
  106.    writeln('The author can be reached at hneely@ac.net');
  107.    writeln;
  108.    halt(0);
  109. end;
  110.  
  111. function num(d:char):word;
  112. begin
  113.    num:= ord(upcase(d)) - 64;
  114. end;
  115.  
  116. function strn(a:integer):string;
  117. var
  118.    s:string;
  119.    i:integer;
  120. begin
  121.    str(a, s);
  122.    if length(s) < 4 then
  123.       for i:= 1 to 4 - length(s) do
  124.          s:= '0' + s;
  125.    strn:= s;
  126. end;
  127.  
  128. function return(s:string; b:boolean):integer;
  129. var
  130.    str:string;
  131.    i, c:integer;
  132. begin
  133.    str:= '';
  134.    if b then
  135.       for i:= 1 to 4 do
  136.          str:= str + s[i]
  137.    else
  138.       for i:= 5 to 8 do
  139.          str:= str + s[i];
  140.    val(str, i, c);
  141.    return:= i;
  142. end;
  143.  
  144. procedure store(filename:string; drive:char);
  145. var
  146.    input, output:file;
  147.    fileinfo, test:searchrec;
  148.    filedata:chksum;
  149.    c, full, disk:longint;
  150.    diskdone:boolean;
  151.    fset, disknum:word;
  152.    success:boolean;
  153.    data:buffer;
  154.    buffersize, readcount, writecount:word;
  155.    ch:char;
  156. begin
  157.    findfirst(filename, anyfile, fileinfo);
  158.    if doserror <> 0 then
  159.       error('File not found: ' + filename);
  160.    new(data);
  161.    c:= 0;
  162.    disknum:= 0;
  163.    diskdone:= true;
  164.    if not DriveExist(drive) then error(drive+': does not exist.');
  165.    randomize;
  166.    fset:= random(9999);
  167.    writeln('This is file set number ', fset, '.');
  168.    assign(input, filename);
  169.    reset(input, 1);
  170.    while c < fileinfo.size do
  171.       begin
  172.          if diskdone then
  173.             begin
  174.                if disknum <> 0 then
  175.                   close(output);
  176.                clreol;
  177.                disk:= 0;
  178.                disknum:= disknum + 1;
  179.                write('Insert disk ', disknum, ' and press [ENTER].');
  180.                readln;
  181.                diskdone:= false;
  182.                buffersize:= sizeof(arraybuf);
  183.                full:= disksize(num(drive));
  184.                if disknum = 1 then
  185.                   begin
  186.                      writeln('Approximately ', (1+(fileinfo.size div disksize(num(drive)))), ' of these disks are needed.');
  187.                      write('Continue? (Y/N)');
  188.                      ch:= readkey;
  189.                      if not ((ch = 'y') or (ch = 'Y')) then
  190.                         halt(0);
  191.                      writeln;
  192.                   end;
  193.                if disksize(num(drive)) <> diskfree(num(drive)) then
  194.                   begin
  195.                      findfirst(drive+':\*.cat', anyfile, test);
  196.                      if return(test.name, true) = fset then
  197.                         error('This disk is of this same set.');
  198.                      delete(drive, success);
  199.                      if not success then
  200.                         error('Some existing file(s) on destination disk could not be removed.');
  201.                   end;
  202.                   assign(output, drive+':\'+strn(fset)+strn(disknum)+'.cat');
  203.                   rewrite(output, 1);
  204.                if disknum = 1 then
  205.                   begin
  206.                      assign(filedata, drive+':\check.sum');
  207.                      rewrite(filedata);
  208.                      write(filedata, fileinfo);
  209.                      close(filedata);
  210.                      full:= diskfree(num(drive));
  211.                   end;
  212.             end;
  213.          if full - disk < buffersize then
  214.             begin
  215.                buffersize:= full - disk;
  216.                diskdone:= true;
  217.             end;
  218.          blockread(input, data^, buffersize, readcount);
  219.          if ioresult <> 0 then
  220.             error('Errors on source disk.');
  221.          blockwrite(output, data^, readcount, writecount);
  222.          if ioresult <> 0 then
  223.             error('Errors on target disk.');
  224.          c:= c + readcount;
  225.          disk:= disk + readcount;
  226.          work(fileinfo.size, c);
  227.          if readcount <> writecount then error('Unable to write to disk');
  228.       end;
  229.    clreol;
  230.    close(input);
  231.    close(output);
  232.    dispose(data);
  233. end;
  234.  
  235. procedure retrive(drive:char; path:string);
  236. var
  237.    setnum, disknum:word;
  238.    diskdone, complete:boolean;
  239.    newfile, store:file;
  240.    cs:chksum;
  241.    fileinfo, data:searchrec;
  242.    d:buffer;
  243.    c:longint;
  244.    buffersize, readcount, writecount:word;
  245. begin
  246.    complete:= false;
  247.    chdir(path);
  248.    new(d);
  249.    c:= 0;
  250.    if ioresult <> 0 then
  251.       error(path+' does not exist.');
  252.    diskdone:= true;
  253.    disknum:= 0;
  254.    while not complete do
  255.       begin
  256.          if diskdone then
  257.             begin
  258.                clreol;
  259.                disknum:= disknum + 1;
  260.                if disknum > 1 then
  261.                   close(store);
  262.                diskdone:= false;
  263.                write('Insert disk ', disknum, ' and press [ENTER].');
  264.                readln;
  265.                buffersize:= sizeof(arraybuf);
  266.                if disknum = 1 then
  267.                   begin
  268.                      assign(cs, drive+':\check.sum');
  269.                      reset(cs);
  270.                      if ioresult <> 0 then error('No check sum file.');
  271.                      read(cs, fileinfo);
  272.                      close(cs);
  273.                      assign(newfile, fileinfo.name);
  274.                      rewrite(newfile, 1);
  275.                      findfirst(drive+':\*.cat', archive, data);
  276.                      if doserror = 18 then
  277.                         begin
  278.                            close(newfile);
  279.                            erase(newfile);
  280.                            error('Disk does not contain storage data.');
  281.                         end;
  282.                      assign(store, drive+':\'+data.name);
  283.                      reset(store, 1);
  284.                      setnum:= return(data.name, true);
  285.                      if return(data.name, false) <> disknum then
  286.                         begin
  287.                            close(newfile);
  288.                            erase(newfile);
  289.                            error('Wrong disk.');
  290.                         end;
  291.                      writeln('File set number is: ', setnum);
  292.                   end
  293.                else
  294.                   begin
  295.                      findfirst(drive+':\*.cat', archive, data);
  296.                      if doserror = 18 then
  297.                         begin
  298.                            close(newfile);
  299.                            erase(newfile);
  300.                            error('Disk does not contain storage data.');
  301.                         end;
  302.                      assign(store, drive+':\'+data.name);
  303.                      reset(store, 1);
  304.                      if setnum <> return(data.name, true) then
  305.                         begin
  306.                            close(newfile);
  307.                            erase(newfile);
  308.                            error('Disk is of a different set.');
  309.                         end;
  310.                      if disknum <> return(data.name, false) then
  311.                         begin
  312.                            close(newfile);
  313.                            erase(newfile);
  314.                            error('Wrong disk.');
  315.                         end;
  316.                   end;
  317.             end;
  318.          blockread(store, d^, buffersize, readcount);
  319.          if ioresult <> 0 then
  320.             begin
  321.                close(newfile);
  322.                erase(newfile);
  323.                error('Errors on source disk.');
  324.             end;
  325.          blockwrite(newfile, d^, readcount, writecount);
  326.          if ioresult <> 0 then
  327.             begin
  328.                close(newfile);
  329.                erase(newfile);
  330.                error('Errors on target disk.');
  331.             end;
  332.          c:= c + readcount;
  333.          if writecount <> readcount then
  334.             begin
  335.                close(newfile);
  336.                erase(newfile);
  337.                error('Unable to write to disk.');
  338.             end;
  339.          if buffersize <> readcount then
  340.             diskdone:= true;
  341.          if fileinfo.size = c then complete:= true;
  342.          work(fileinfo.size, c);
  343.       end;
  344.    clreol;
  345.    close(newfile);
  346.    close(store);
  347.    dispose(d);
  348. end;
  349.  
  350. var
  351.    c1, c2:string;
  352.  
  353. begin
  354.    if paramcount = 0 then
  355.       help;
  356.    if paramcount <> 3 then
  357.       error('Incorect number of parameters.');
  358.    c1:= paramstr(1);
  359.    c2:= paramstr(2);
  360.    case c1[1] of
  361.       's', 'S' : store(paramstr(3), c2[1]);
  362.       'r', 'R' : retrive(c2[1], paramstr(3));
  363.    else
  364.       error('Incorect parameters.');
  365.    end;
  366.    writeln('Complete!');
  367. end.
  368.  
  369. { ---------------  CUT ---------------- }
  370.  
  371. unit files;
  372.  
  373. interface
  374.  
  375. uses
  376.    dos;
  377.  
  378. type
  379.    filetype = string[12];
  380.    {searchrec = record    This is how searchrec is defined in the DOS unit.
  381.       Fill: array[1..21] of Byte;
  382.       Attr: Byte;
  383.       Time: Longint;
  384.       Size: Longint;
  385.       Name: string[12];
  386.    end;  }
  387.    filestack = ^ node;
  388.    node = record
  389.       fileinfo:searchrec;
  390.       next:filestack;
  391.    end;
  392.    directory_tree = ^dnode;
  393.    dnode = record
  394.       dir:string;
  395.       lower_dir:directory_tree;
  396.       next:directory_tree;
  397.    end;
  398.  
  399. procedure fill_filestack(var stack:filestack);
  400.    {Fills stack of type filestack with all the file enteries in the
  401.    current directory.  Includes directoies and hidden file types.}
  402.  
  403. procedure push_filestack(var stack:filestack; item:searchrec);
  404.    {Pushes in alfa order a new node on a filestack.}
  405.  
  406. procedure fill_dirtree(dir:string; var tree:directory_tree);
  407.    {Fills a tree sturcture with the directory structure using dir string
  408.    as the root.}
  409.  
  410. implementation
  411.  
  412. procedure push_filestack(var stack:filestack; item:searchrec);
  413. var
  414.    temp:filestack;
  415.  
  416.    procedure insert(var stack, prev:filestack);
  417.    begin
  418.       if (stack = nil) then
  419.          begin
  420.             temp^.next:= stack;
  421.             stack:= temp;
  422.          end
  423.       else
  424.          if temp^.fileinfo.name > stack^.fileinfo.name then
  425.             insert(stack^.next, stack)
  426.          else
  427.             if temp^.fileinfo.name < stack^.fileinfo.name then
  428.                begin
  429.                   if prev = stack then
  430.                      begin
  431.                         temp^.next:= stack;
  432.                         stack:= temp;
  433.                      end
  434.                   else
  435.                      begin
  436.                         temp^.next:= stack;
  437.                         prev^.next:= temp;
  438.                      end;
  439.                end;
  440.    end;
  441. begin
  442.    new(temp);
  443.    temp^.fileinfo:= item;
  444.    insert(stack, stack);
  445. end;
  446.  
  447. procedure fill_filestack(var stack:filestack);
  448. var
  449.    dirinfo:searchrec;
  450. begin
  451.    findfirst('*.*', anyfile, dirinfo);
  452.    while doserror <> 18 do
  453.       begin
  454.          push_filestack(stack, dirinfo);
  455.          findnext(dirinfo);
  456.       end;
  457. end;
  458.  
  459. procedure push(var head:directory_tree; item:string);
  460. var
  461.    temp:directory_tree;
  462. begin
  463.    new(temp);
  464.    temp^.dir:= item;
  465.    temp^.next:= head;
  466.    head:= temp;
  467.    head^.lower_dir:= nil;
  468. end;
  469.  
  470. procedure fill_dirtree(dir:string; var tree:directory_tree);
  471. procedure fill_dirlist(var head:directory_tree; directory:string; s:integer);
  472. var
  473.    place:directory_tree;
  474.    dirinfo:searchrec;
  475.    found:boolean;
  476. begin
  477.    writeln(directory);
  478.    chdir(directory);
  479.    findfirst('*.*', 16, dirinfo);
  480.    while doserror = 0 do
  481.       begin
  482.          if (dirinfo.attr = 16) and ((dirinfo.name <> '..') and (dirinfo.name <> '.'))then
  483.             begin
  484.                push(head, fexpand(dirinfo.name));
  485.                found:= true;
  486.             end;
  487.             findnext(dirinfo);
  488.          end;
  489.       if found then
  490.          begin
  491.             place:= head;
  492.             while place <> nil do
  493.                begin
  494.                   fill_dirlist(place^.lower_dir, place^.dir, s+3);
  495.                   place:= place^.next;
  496.                end;
  497.          end;
  498. end;
  499.  
  500. var
  501.    temp:directory_tree;
  502. begin
  503.    tree:= nil;
  504.    fill_dirlist(tree, dir, 0);
  505.    new(temp);
  506.    temp^.dir:= dir;
  507.    temp^.lower_dir:= tree;
  508.    temp^.next:= nil;
  509.    tree:= temp;
  510. end;
  511.  
  512. end.